package com.tabnet.form.client;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.joda.time.DateTime;

import com.tabnet.beans.personnes.Adresse;
import com.tabnet.beans.personnes.Client;
import com.tabnet.dao.DAOClient;
import com.tabnet.dao.DAOException;
import com.tabnet.form.FormValidationException;

public class ModificationClientForm {
	  	private static final String CHAMP_NOM		= "nomClient";
	    private static final String CHAMP_PRENOM	= "prenomClient";
	    private static final String CHAMP_NAISSANCE	= "dateClient";
	    private static final String CHAMP_TELEPHONE	= "telephoneClient";
	    private static final String CHAMP_MAIL		= "emailClient";
	    private static final String CHAMP_MDP		= "mdpClient";
	    private static final String CHAMP_CONFMDP	= "confClient";
	    private static final String CHAMP_RUE		= "adresseRueClient";
	    private static final String CHAMP_CP		= "adresseCPClient";
	    private static final String CHAMP_VILLE		= "adresseVilleClient";
	    private static final String CHAMP_PAYS		= "adressePaysClient";
	    private static final String CHAMP_VALIDMDP	= "mdpValid";
	    

	    private String resultat = "";
	    private Map<String, String> erreurs = new HashMap<String, String>();
	    private DAOClient oClientDao;


	    public ModificationClientForm( DAOClient pClientDao ) {
	        this.oClientDao = pClientDao;
	    }

	    public Map<String, String> getErreurs() {
	        return this.erreurs;
	    }
	    public String getResultat() {
	        return this.resultat;
	    }
	    
	    /**
	     * <p>Fonction modifClient<br />
	     * Modifie un client à partir des données entrées par l'utilisateur.
	     * Si aucune erreur, le client est modifier dans la base de données
	     * sinon l'utilisateur doit corriger les erreurs.</p>
	     * @param request : objet HttpServletRequest
	     * @param Client : objet Client
	     * @return une instance Client
	     */
	    public Client modifClient( HttpServletRequest request, Client pClient ) {
	    	
	    	// récupération des valeurs
	        String nom = getValeurChamp( request, CHAMP_NOM );
	        String prenom = getValeurChamp( request, CHAMP_PRENOM );
	        String telephone = getValeurChamp( request, CHAMP_TELEPHONE );
	        String naissance = getValeurChamp( request, CHAMP_NAISSANCE );
	        
	        String rue = getValeurChamp( request, CHAMP_RUE );
	        String ville = getValeurChamp( request, CHAMP_VILLE );
	        String cp = getValeurChamp( request, CHAMP_CP );
	        String pays = getValeurChamp( request, CHAMP_PAYS );
	        
	        String mail = getValeurChamp( request, CHAMP_MAIL );
	        String mdp = getValeurChamp( request, CHAMP_MDP );
	        String confMDP = getValeurChamp( request, CHAMP_CONFMDP );
	        
	        String validModif = getValeurChamp( request, CHAMP_VALIDMDP );

	        // création des objets
	        Client oClient = new Client();
	        Adresse oAdresse = new Adresse();

	        oClient.setId(pClient.getId());
	        
	        // les tests de validation des données
	        if(!nom.equals(pClient.getNom()))
	        	this.traiterNom(nom, oClient);
	        else
	        	oClient.setNom(pClient.getNom());
	        	        	
	        if(!prenom.equals(pClient.getPrenom()))
	        	this.traiterPrenom(prenom, oClient);
	        else
	        	oClient.setPrenom(pClient.getPrenom());

	        if(!telephone.equals(pClient.getTelephone()))
	        	this.traiterTelephone(telephone, oClient);
	        else
	        	oClient.setTelephone(pClient.getTelephone());

	        if(!naissance.equals(pClient.getNaissance().toString("yyyy-MM-dd")))
	        	this.traiterDate(naissance, oClient);
	        else
	        	oClient.setNaissance(pClient.getNaissance());

	        // Adresse
	        oAdresse.setId(pClient.getAdresse().getId());
	        
	        if(!rue.equals(pClient.getAdresse().getRue()))
	        	this.traiterRue(rue, oAdresse);
	        else
	        	oAdresse.setRue(pClient.getAdresse().getRue());
	        
	        if(!ville.equals(pClient.getAdresse().getVille()))
	        	this.traiterVille(ville, oAdresse);
	        else
	        	oAdresse.setVille(pClient.getAdresse().getVille());
	        
	        if(!cp.equals(pClient.getAdresse().getCodePostal()))
	        	this.traiterCP(cp, oAdresse);
	        else
	        	oAdresse.setCodePostal(pClient.getAdresse().getCodePostal());
	        
	        if(!pays.equals(pClient.getAdresse().getPays()))
	        	this.traiterPays(pays, oAdresse);
	        else
	        	oAdresse.setPays(pClient.getAdresse().getPays());

	        // Connexion
	        if(!mail.equals(pClient.getMail()))
		        this.traiterMail(mail, oClient);
	        else
	        	oClient.setMail(pClient.getMail());
	        
	        boolean modifMDP = false;
	        
	        if(mdp != null && !mdp.isEmpty() || confMDP != null && !confMDP.isEmpty())
	        	modifMDP = this.traiterMdp(mdp, confMDP, oClient);
	        else
	        	oClient.setMDP(pClient.getMDP());
	        
	                
	        oClient.setAdresse(oAdresse);

	        try {
	            if ( this.erreurs.isEmpty() ) {
	            	this.oClientDao.updClient(oClient, validModif, modifMDP);
	                this.resultat = "Succès de la modification du client.";
	            }
	            else
	                this.resultat = "Échec de la modification du client.";
	        }
	        catch ( DAOException e ) {
	        	this.setErreur( "imprévu", "Erreur imprévue lors de la mise à jour dans la base de données." );
	            this.resultat = e.getMessage() + "<br /> Échec de la modification du client.";
	            oClient = pClient;
	        }

	        return oClient;
	    }
	    
	    /**
	     * Procédure traiterNom
	     * Contrôle le nom du client
	     * @param pNom: nom du client
	     * @param pClient: objet Client
	     * */
	    private void traiterNom( String pNom, Client pClient ) {
	        try {
	            this.validationNom( pNom );
	        } catch ( Exception e ) {
	            this.setErreur( CHAMP_NOM, e.getMessage() );
	        }
	        pClient.setNom( pNom );
	    }
	    
	    /**
	     * Procédure traiterPrenom
	     * Contrôle le prenom du client
	     * @param pPrenom: prenom du client
	     * @param pClient: objet Client
	     * */
	    private void traiterPrenom( String pPrenom, Client pClient ) {
	        try {
	            this.validationPrenom(pPrenom);
	        } catch ( Exception e ) {
	            this.setErreur( CHAMP_PRENOM, e.getMessage() );
	        }
	        pClient.setPrenom( pPrenom );
	    }
	    /**
	     * 
	     * Procédure traiterTelephone
	     * Contrôle le telephone du client
	     * @param pTelephone: telephone du client
	     * @param pClient: objet Client
	     * */
	    private void traiterTelephone( String pTelephone, Client pClient ) {
	        try {
	            this.validationTelephone(pTelephone);
	        } catch ( Exception e ) {
	            this.setErreur( CHAMP_TELEPHONE, e.getMessage() );
	        }
	        pClient.setTelephone( pTelephone );
	    }
	    
	    /**
	     * Procédure traiterDate
	     * Contrôle la date de naissance du client
	     * @param pDate: date de naissance du client
	     * @param pClient: objet Client
	     * */
	    private void traiterDate( String pDate, Client pClient ) {
	        try {
	            this.validationDate(pDate);
	        } catch ( Exception e ) {
	            this.setErreur( CHAMP_NAISSANCE, e.getMessage() );
	        }
	        pClient.setNaissance( new DateTime( pDate ));
	    }
	    
	    /**
	     * Procédure traiterRue
	     * Contrôle la rue du client
	     * @param pRue: rue du client
	     * @param pAdresse: objet Adresse
	     * */
	    private void traiterRue( String pRue, Adresse pAdresse ) {
	        try {
	        	this.validationRue( pRue );
	        } catch ( Exception e ) {
	            this.setErreur( CHAMP_RUE, e.getMessage() );
	        }
	        pAdresse.setRue( pRue );
	    }
	    
	    /**
	     * Procédure traiterCP
	     * Contrôle le code postal du client
	     * @param pCP: code postal du client
	     * @param pAdresse: objet Adresse
	     * */
	    private void traiterCP( String pCP, Adresse pAdresse ) {
	        try {
	        	this.validationCP( pCP );
	        } catch ( Exception e ) {
	            this.setErreur( CHAMP_CP, e.getMessage() );
	        }
	        pAdresse.setCodePostal( pCP );
	    }
	    
	    /**
	     * Procédure traiterVille
	     * Contrôle lav ille du client
	     * @param pVille: ville du client
	     * @param pAdresse: objet Adresse
	     * */
	    private void traiterVille( String pVille, Adresse pAdresse ) {
	        try {
	        	this.validationVille( pVille );
	        } catch ( Exception e ) {
	            this.setErreur( CHAMP_VILLE, e.getMessage() );
	        }
	        pAdresse.setVille( pVille );
	    }
	    
	    /**
	     * Procédure traiterPays
	     * Contrôle le pays du client
	     * @param pPays: pays du client
	     * @param pAdresse: objet Adresse
	     * */
	    private void traiterPays( String pPays, Adresse pAdresse ) {
	        try {
	        	this.validationPays( pPays );
	        } catch ( Exception e ) {
	            this.setErreur( CHAMP_PAYS, e.getMessage() );
	        }
	        pAdresse.setPays(pPays);
	    }
	    
	    /**
	     * Procédure traiterMail
	     * Contrôle le mail du client
	     * @param pMail: mail du client
	     * @param pClient: objet Client
	     * */
	    private void traiterMail( String pMail, Client pClient ) {
	        try {
	            this.validationMail( pMail, pClient.getId());
	        } catch ( Exception e ) {
	            this.setErreur( CHAMP_MAIL, e.getMessage() );
	        }
	        pClient.setMail( pMail );
	    }
	    
	    /**
	     * Procédure traiterMdp
	     * Contrôle le mot de passe du client
	     * @param pMDP: mot de passe du client
	     * @param pMDPConf: confirmation du mot de passe client
	     * @param pClient: objet Client
	     * @return true si le mot de passe doit être changer
	     * */
	    private boolean traiterMdp( String pMDP, String pMDPConf, Client pClient ) {
	        try {
	            this.validationMdp( pMDP, pMDPConf );
	        } catch ( Exception e ) {
	            this.setErreur( CHAMP_MDP, e.getMessage() );
	            return false;
	        }
	        pClient.setMDP( pMDP );
	        return true;
	    }
	    
	    /**
	     * LES VALIDATIONS
	     * */
	    
	    private void validationNom( String pNom ) throws FormValidationException {
	        if ( pNom == null || pNom.length() < 2 )
	            throw new FormValidationException( "Le nom doit contenir au moins 2 caractères." );
	    }
	    
	    private void validationPrenom( String pPrenom ) throws FormValidationException {
	        if ( pPrenom != null && pPrenom.length() < 2 )
	            throw new FormValidationException( "Le prenom doit contenir au moins 2 caractères." );
	    }
	    
	    private void validationTelephone( String pTelephone ) throws FormValidationException {
	        if ( pTelephone != null ) {
	            if ( !pTelephone.matches( "^0\\d([-.\\s]?\\d{2}){4}$" ) ) //  ^\\d+$
	                throw new FormValidationException( "Le numéro de téléphone doit uniquement contenir des chiffres." );
	            else if ( pTelephone.length() < 10 )
	                throw new FormValidationException( "Le numéro de téléphone doit ctyontenir au moins 10 caractères." );
	        }
	        else
	            throw new FormValidationException( "Merci d'entrer un numéro de téléphone." );
	    }
	    
	    private void validationDate( String pDate ) throws FormValidationException{
	    	if ( pDate != null && !pDate.isEmpty()) {
	    		DateTime date = new DateTime(pDate);
	    		
	            if ( date.isAfterNow() )
	                throw new FormValidationException( "La date de naissance ne peut être supérieur à la date actuelle." );
	            
	            if ( date.plusYears(18).isAfterNow()  )
	                throw new FormValidationException( "Vous devez avoir 18 ans pour vous inscrire." );
	        }
	        else
	            throw new FormValidationException( "Merci d'entrer une date de naissance." );
	    }
	    
	    private void validationRue( String pRue ) throws FormValidationException {
	        if ( pRue != null ) {
	            if ( pRue.length() < 5 )
	                throw new FormValidationException( "La rue du client doit contenir au moins 5 caractères." );
	        }
	        else
	            throw new FormValidationException( "Merci d'entrer la rue du client." );
	    }

	    private void validationCP( String pCP ) throws FormValidationException {
	        if ( pCP != null ) {
	            if ( pCP.length() < 5 )
	                throw new FormValidationException( "Le numéro de code postal doit contenir au moins 5 chiffres." );
	        }
	        else
	            throw new FormValidationException( "Merci d'entrer un code postal." );
	    }
	    
	    private void validationVille( String pVille ) throws FormValidationException {
	        if ( pVille != null ) {
	            if ( pVille.length() < 2 )
	                throw new FormValidationException( "La ville du client doit contenir au moins 2 caractères." );
	        }
	        else
	            throw new FormValidationException( "Merci d'entrer la ville du client." );
	    }
	    
	    private void validationPays( String pPays ) throws FormValidationException {
	        if ( pPays != null ) {
	            if ( pPays.length() < 2 )
	                throw new FormValidationException( "Le pays du client doit contenir au moins 2 caractères." );
	        }
	        else
	            throw new FormValidationException( "Merci d'entrer le pays du client." );
	    }
	    
	    private void validationMail( String pMail, int pId ) throws FormValidationException, DAOException {
	    	if(!this.oClientDao.checkMail(pMail, pId))
	    		throw new FormValidationException( "Adresse mail déjà existante." );
	    	else{
		        if ( pMail == null || !pMail.matches( "([^.@]+)(\\.[^.@]+)*@([^.@]+\\.)+([^.@]+)" ) )
		            throw new FormValidationException( "Merci de saisir une adresse mail valide." );
	    	}
	    }
	    
	    private void validationMdp( String pMDP, String pConfMDP ) throws FormValidationException {
	        if ( pMDP != null ) {
	            if ( pMDP.length() < 5 ) {
	                throw new FormValidationException( "Le mot de passe du fournisseur doit contenir au moins 5 caractères." );
	            }
	            else if(!pMDP.equals(pConfMDP))
	                throw new FormValidationException( "La confirmation du mot de passe n'est pas identique." );
	        }
	        else
	            throw new FormValidationException( "Merci d'entrer un mot de passe Fournisseur." );
	    }

	    /*
	     * Ajoute un message correspondant au champ spécifié à la map des erreurs.
	     */
	    private void setErreur( String champ, String message ) {
	        this.erreurs.put( champ, message );
	    }

	    private static String getValeurChamp( HttpServletRequest request, String nomChamp ) {
	        String valeur = request.getParameter( nomChamp );
	        if ( valeur == null || valeur.trim().length() == 0 )
	            return null;
	        else
	            return valeur;
	    }
}
